#pragma once
#include "Comm.h"
#include "CommType.h"
#include "Atom.h"

namespace COMM
{
	class COMM_API Thread
	{
		MYLIB_NONCOPIED_CLASS(Thread);
	public:
#ifdef COMM_MSVC
		typedef HANDLE handle;
#else
		typedef pthread_t handle;
#endif
		enum { EXIT_MIN=0x7FFFFFF0, EXIT_CANCELED, EXIT_TIMEOUT, EXIT_ERROR, EXIT_MAX};
		enum State{ TS_INIT=0, TS_RUNNING, TS_EXIT};
		static void Sleep(unsigned int timeoutMs = -1);
		// pseudo id in __CYGWIN__ version.
		static int Id();
		typedef int (*ThreadProc)(CommType& arg);
		// ScopedPtr<Thread> should be used to release the returned instance after thread is run over.
		static Thread* Run(ThreadProc proc,const CommType& arg=CommType::Null,const char* threadName=NULL);

		Thread(const char* threadName=NULL);
		virtual ~Thread(void);
		handle Handle() const;
		const char* Name() const;
		void Run();
		// cancel thread.
		void Terminate();
		// retrieve exit code, then you can re-run.
		int Join(unsigned int timeoutMs=-1);

	protected:
		virtual int Process() = 0;
	private:
#ifdef COMM_MSVC
		static DWORD WINAPI __ThreadProc(void* arg);
#else
		static void* __ThreadProc(void* arg);
#endif
	private:
		AtomInt m_state;
		String m_name;
		handle m_thread;
#ifndef COMM_MSVC
		pthread_attr_t m_attr;		
#endif
		int m_exitcode;
	};
}


